﻿// -----------------------------------------------------------------------
// <copyright file="Smoothing.cs" company="Fcis">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

namespace IP_Package.Operations.Neighbor_operations
{
    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using IPPackage;
    using IPPackage.ImageOperation;

    /// <summary>
    /// TODO: Update summary.
    /// </summary>
    public class Smoothing : LinearConvolution
    {
        /// <summary>
        /// Smothings the specified image.
        /// </summary>
        /// <param name="maskSizeOrSegma">The mask size or segma.</param>
        /// <param name="type">The type of smothing.</param>
        /// <returns>the new image</returns>
        public Bitmap MakeSmoothing(double maskSizeOrSegma, string type)
        {
            try
            {
                Color[,] buffer = this.AddBorder(maskSizeOrSegma);
                Mask mask = new Mask();
                if (type == "mean")
                {
                    mask = this.SmoothingMean((int)maskSizeOrSegma);
                    mask.MaskSize = (int)maskSizeOrSegma;
                }
                else if (type == "gaussian")
                {
                    mask = this.SmoothingGaussian(maskSizeOrSegma);
                }

                return this.LinearConvolutionFn(buffer, mask, "None");
            }
            catch (Exception ex)
            {
                IPPackage.Logger.LogException(ex);
                throw ex;
            }
        }

        /// <summary>
        /// Gaussians the fn.
        /// </summary>
        /// <param name="x">The x.</param>
        /// <param name="y">The y.</param>
        /// <param name="segma">The segma.</param>
        /// <returns>the return value of the function</returns>
        public double GaussianFn(int x, int y, double segma)
        {
            try
            {
                return (1 / (2 * Math.PI * segma * segma)) * Math.Exp((-((x * x) + (y * y))) / (2 * segma * segma));
            }
            catch (Exception ex)
            {
                IPPackage.Logger.LogException(ex);
                throw ex;
            }
        }

        /// <summary>
        /// generate the Smothings mean mask based on the mask size.
        /// </summary>
        /// <param name="maskSize">Size of the mask.</param>
        /// <returns>the mask</returns>
        public Mask SmoothingMean(int maskSize)
        {
            try
            {
                Mask m;
                m.MaskSize = maskSize;
                m.MaskValues = new double[maskSize, maskSize];
                double value = 1.0 / (maskSize * maskSize);
                for (int i = 0; i < maskSize; i++)
                {
                    for (int j = 0; j < maskSize; j++)
                    {
                        m.MaskValues[i, j] = value;
                    }
                }

                return m;
            }
            catch (Exception ex)
            {
                IPPackage.Logger.LogException(ex);
                throw ex;
            }
        }

        /// <summary>
        /// generate the Smothings gaussian mask based on the segma.
        /// </summary>
        /// <param name="segma">The segma.</param>
        /// <returns>the mask</returns>
        public Mask SmoothingGaussian(double segma)
        {
            try
            {
                Mask m;
                m.MaskSize = (2 * (int)((3.7 * segma) - 0.5)) + 1;
                m.MaskValues = new double[m.MaskSize, m.MaskSize];
                int tempHieght = -m.MaskSize / 2;
                int tempWidth = -m.MaskSize / 2;
                double sum = 0;
                for (int i = 0; i < m.MaskSize; i++)
                {
                    for (int j = 0; j < m.MaskSize; j++)
                    {
                        m.MaskValues[j, i] = this.GaussianFn(j + tempWidth, i + tempHieght, segma);
                        sum += m.MaskValues[j, i];
                    }
                }

                for (int i = 0; i < m.MaskSize; i++)
                {
                    for (int j = 0; j < m.MaskSize; j++)
                    {
                            m.MaskValues[j, i] *= 1 / sum;
                    }
                }

                return m;
            }
           catch (Exception ex)
            {
               Logger.LogException(ex);
               throw ex;
            }
        }
    }
}
